import * as Cesium from 'cesium'
import { CircleWaveMaterialProperty } from './CircleWaveMaterialProperty.js'

/**
 * 无人机图标颜色枚举
 * 0: 类型A (例如：个人)
 * 1: 类型B (例如：企业)
 * 2: 类型C (例如：政府)
 */
export const colorOwner = {
  0: '#E0BD0CFF',
  1: '#07f5cc',
  2: '#43b4ff'
}

/**
 * 无人机图层类
 */
export default class UavModelHisLayer {

  // 轨迹信息
  historyInfo = {}

  constructor(Viewer, uavLayer) {
    this.viewer = Viewer
    this.uavLayer = uavLayer
    this.uavIconUrl = ''
    this.uavModelUrl = '/model/SXY800.glb'
  }

  /**
   * 创建无人机实体
   * @param {string} snCode - 无人机序列号
   * @param {Object} position - 位置属性
   * @param {Object} options - 其他配置选项
   * @param {string} options.idText - 显示的ID文本
   * @param {string} options.infoText - 显示的信息文本
   * @param {number} options.ownerType - 拥有者类型
   * @param {string} options.img - 图标图片
   * @param {Array} options.initPostion - 初始位置 [经度, 纬度, 高度]
   * @returns {Cesium.Entity} 创建的无人机实体
   */
  createUavEntity (snCode, position, options) {
    const { idText, infoText, ownerType, img, initPostion } = options;

    // 创建默认的orientation绑定
    const velocityVector = new Cesium.VelocityVectorProperty(position, true);
    const initialCartesian = Cesium.Cartesian3.fromDegrees(initPostion[0], initPostion[1], initPostion[2]);
    const enuTransform = Cesium.Transforms.eastNorthUpToFixedFrame(initialCartesian);
    const inverseEnu = new Cesium.Matrix4();
    Cesium.Matrix4.inverse(enuTransform, inverseEnu);
    const velocityEnu = new Cesium.Cartesian3();
    let heading = Cesium.Math.toRadians(0) // 设置无人机的航向角度为0度
    let pitch = Cesium.Math.toRadians(0) // 设置无人机的俯仰角度为0度
    let roll = Cesium.Math.toRadians(0) // 设置无人机的滚转角度为0度
    let hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll)

    const orientation = new Cesium.CallbackProperty((time, result) => {
      const pos = position.getValue(time)
      const velocityEcef = velocityVector.getValue(time);

      if (!Cesium.defined(velocityEcef)) return undefined
      Cesium.Matrix4.multiplyByPointAsVector(inverseEnu, velocityEcef, velocityEnu);

      // 获取东北天坐标系中的速度分量
      const eastSpeed = velocityEnu.x;   // 东向速度
      const northSpeed = velocityEnu.y;  // 北向速度
      const upSpeed = velocityEnu.z;     // 垂直向上速度

      const horizontalSpeed = Math.abs(Math.sqrt(eastSpeed * eastSpeed + northSpeed * northSpeed));
      const verticalSpeed = Math.abs(upSpeed);

      // 水平运动
      if (Math.round(horizontalSpeed) && !Math.round(verticalSpeed)) {
        hpr.heading = -Math.atan2(northSpeed, eastSpeed);
      }
      return Cesium.Transforms.headingPitchRollQuaternion(
        pos,
        hpr,
        Cesium.Ellipsoid.WGS84,
        Cesium.Transforms.eastNorthUpToFixedFrame,
        result
      );
    }, false);

    return new Cesium.Entity({
      id: snCode,
      position: position,
      orientation: orientation,
      model: {
        uri: this.uavModelUrl,
        minimumPixelSize: 64,
        scale: 1.0,
        // 添加近距离显示条件：只在0-500米范围内显示模型
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 500),
        color: new Cesium.Color(1.0, 1.0, 1.0, 1.0)  // 修改透明度为1.0，使模型可见
      },
      billboard: {
        image: img,
        scale: 1.0,
        heightReference: Cesium.HeightReference.NONE,
        clampToGround: false, // 是否贴地
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
        // 添加距离缩放效果：近距离(0-100000)保持原始大小1.0，远距离(150000米)缩小到0.3
        scaleByDistance: new Cesium.NearFarScalar(100000, 1.0, 150000, 0.3),
        // 只在远距离(超过500米)显示billboard
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(500, 2000000),
      },
      label: {
        text: `${idText}\n${infoText}`,
        font: '32px Microsoft YaHei Bold',
        scale: 0.5,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        fillColor: Cesium.Color.fromCssColorString('#FFFFFF'),
        outlineColor: Cesium.Color.fromCssColorString(colorOwner[ownerType]),
        outlineWidth: 5,
        horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
        pixelOffset: new Cesium.Cartesian2(20, -10),
        heightReference: Cesium.HeightReference.NONE,
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
        // 只在远距离(超过500米)显示label
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(500, 150000),
        // 可以根据需要调整垂直对齐方式
        verticalOrigin: Cesium.VerticalOrigin.CENTER
      },
      ellipse: {
        show: false,
        semiMinorAxis: 500,
        semiMajorAxis: 500,
        material: new CircleWaveMaterialProperty({
          duration: 4000,
          // color: "#00FF00" // 绿色
        }),
      }
    })
  }


  /**
   * 判断是否存在无人机
   * @param {*} snCode 
   * @returns 
   */
  hasUav (snCode) {
    return this.uavLayer.has(snCode)
  }

  /**
   * 清除无人机
   * @param {string} snCode - 无人机序列号，如果不传则清除所有无人机
   */
  clearUav (snCode) {
    if (snCode) {
      // 清除指定无人机
      if (!this.hasUav(snCode)) return false;

      const uavItem = this.uavLayer.get(snCode);
      if (uavItem.uavIcon) this.viewer.entities.remove(uavItem.uavIcon);
      if (uavItem.alarmWave) this.viewer.entities.remove(uavItem.alarmWave);
      this.uavLayer.delete(snCode);
      return true;
    } else {
      // 清除所有无人机
      this.uavLayer.forEach((uavItem) => {
        if (uavItem.uavIcon) this.viewer.entities.remove(uavItem.uavIcon);
        if (uavItem.alarmWave) this.viewer.entities.remove(uavItem.alarmWave);
      });
      this.uavLayer.clear();
      return true;
    }
  }  /**
   * 显示/隐藏无人机
   * @param {string} snCode - 无人机序列号，如果不传则控制所有无人机
   * @param {boolean} show - 是否显示，默认为true
   */
  showUav (snCode, show = true) {
    // 设置单个无人机实体及其子组件的显示状态
    const setUavVisibility = (uavItem) => {
      const { uavIcon } = uavItem;
      // 设置实体和所有子组件的显示状态
      ['show', 'billboard', 'model', 'label', 'ellipse', 'path'].forEach(prop => {
        if (prop === 'show') {
          uavIcon.show = show;
        } else if (uavIcon[prop]) {
          uavIcon[prop].show = show;
        }
      });
    };

    if (snCode) {
      // 控制指定无人机的显示
      if (!this.hasUav(snCode)) return false;
      setUavVisibility(this.uavLayer.get(snCode));
      return true;
    } else {
      // 控制所有无人机的显示
      this.uavLayer.forEach(setUavVisibility);
      return true;
    }
  }  /**
   * 加载无人机轨迹并播放
   * @param {Object} uavInfo - 无人机信息对象，包含 snCode, ownerType, productCode 等
   * @param {Array} uavTrack - 轨迹数据数组，每个元素为 [经度, 纬度, 高度]
   * @returns {Object|null} 返回时间信息对象 { totalDuration, startTime(JulianDate), stopTime(JulianDate), timeInterval, playbackSpeed }，轨迹为空时返回null
   */
  loadUavTrack (uavInfo, uavTrack) {
    if (!uavTrack || uavTrack.length === 0) {
      console.warn('轨迹数据为空');
      return null;
    }

    const { snCode, ownerType, productCode, img } = uavInfo;

    // 移除已存在的无人机
    if (this.hasUav(snCode)) {
      const uavItem = this.uavLayer.get(snCode);
      this.viewer.entities.remove(uavItem.uavIcon);
      this.uavLayer.delete(snCode);
    }

    // 创建时间间隔（每个轨迹点间隔1秒）
    const timeInterval = 1; // 秒
    const startTime = Cesium.JulianDate.fromDate(new Date());

    // 创建采样位置属性
    const sampledPosition = new Cesium.SampledPositionProperty();
    sampledPosition.setInterpolationOptions({
      interpolationDegree: 1,
      interpolationAlgorithm: Cesium.LinearApproximation
    });

    // 添加轨迹点到采样位置
    uavTrack.forEach((trackPoint, index) => {
      const [longitude, latitude, altitude] = trackPoint;
      const time = Cesium.JulianDate.addSeconds(startTime, index * timeInterval, new Cesium.JulianDate());
      const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, altitude);
      sampledPosition.addSample(time, position);
    });

    // 设置轨迹的可用性时间间隔
    const totalDuration = uavTrack.length * timeInterval;
    const stopTime = Cesium.JulianDate.addSeconds(startTime, totalDuration, new Cesium.JulianDate());
    const availability = new Cesium.TimeIntervalCollection([
      new Cesium.TimeInterval({
        start: startTime,
        stop: stopTime
      })
    ]);

    // 创建无人机实体的配置
    const idText = productCode ? productCode : snCode.substring(4).split('-')[0];
    const infoText = `轨迹播放中`;
    const firstPoint = uavTrack[0];

    // 使用抽取的函数创建无人机实体
    const uavIcon = this.createUavEntity(snCode, sampledPosition, {
      idText,
      infoText,
      ownerType: ownerType || 0,
      img: img || '/img/uav_2_1.svg',
      initPostion: firstPoint
    });

    // 设置实体的可用性
    uavIcon.availability = availability;

    // 添加轨迹线
    uavIcon.path = {
      show: true,
      leadTime: 0,
      trailTime: totalDuration,
      width: 3,
      resolution: 1,
      material: new Cesium.PolylineGlowMaterialProperty({
        glowPower: 0.3,
        color: Cesium.Color.fromCssColorString(colorOwner[ownerType || 0])
      })
    };    // 添加到场景
    this.viewer.entities.add(uavIcon);    // 创建时间信息对象
    const timeInfo = {
      totalDuration: totalDuration,        // 总时间（秒）
      startTime: startTime,                // 开始时间（JulianDate格式）
      stopTime: stopTime,                  // 结束时间（JulianDate格式）
      currentTime: null,
      timeInterval: timeInterval,          // 时间间隔（秒）
      playbackSpeed: 1.0                   // 播放速度（默认1倍速）
    };

    // 保存到图层
    this.uavLayer.set(snCode, {
      uavIcon,
      alarmWave: undefined,
      isTrackMode: true,
      timeInfo: timeInfo
    });

    // 保存历史信息
    this.historyInfo[snCode] = timeInfo;

    // 返回时间信息
    return timeInfo;
  }

  /**
   * 跳转到历史轨迹的指定时间点
   * @param {string} snCode - 无人机序列号
   * @param {number} time - 相对轨迹开始时间的秒数（例如：传入30表示轨迹开始后的第30秒）
   * @returns {boolean} 是否跳转成功
   */
  jumpToHistoryPoint (snCode, time) {
    // 检查无人机是否存在
    if (!this.hasUav(snCode)) {
      console.warn(`无人机 ${snCode} 不存在`);
      return false;
    }

    const uavItem = this.uavLayer.get(snCode);

    // 检查是否为轨迹模式
    if (!uavItem.isTrackMode) {
      console.warn(`无人机 ${snCode} 不在轨迹模式`);
      return false;
    }

    // 获取时间信息
    const timeInfo = this.historyInfo[snCode];
    if (!timeInfo) {
      console.warn(`无人机 ${snCode} 的时间信息不存在`);
      return false;
    }

    // 验证时间参数类型
    if (typeof time !== 'number') {
      console.error(`时间参数必须为数字类型，当前类型为: ${typeof time}`);
      return false;
    }

    // 验证时间范围
    if (time < 0 || time > timeInfo.totalDuration) {
      console.warn(`时间参数 ${time} 超出有效范围 [0, ${timeInfo.totalDuration}]`);
      return false;
    }    // 计算目标时间：轨迹开始时间 + 传入的秒数
    const trackStartTime = timeInfo.startTime;
    const targetTime = Cesium.JulianDate.addSeconds(trackStartTime, time, new Cesium.JulianDate());

    // 检查目标时间是否在轨迹的时间范围内（双重检查）
    const trackStopTime = timeInfo.stopTime;

    if (Cesium.JulianDate.lessThan(targetTime, trackStartTime) || Cesium.JulianDate.greaterThan(targetTime, trackStopTime)) {
      console.warn(`目标时间 ${Cesium.JulianDate.toIso8601(targetTime)} 超出轨迹时间范围 [${Cesium.JulianDate.toIso8601(timeInfo.startTime)}, ${Cesium.JulianDate.toIso8601(timeInfo.stopTime)}]`);
      return false;
    }// 检查目标时间是否在可用性范围内
    const availability = uavItem.uavIcon.availability;
    if (availability && !availability.contains(targetTime)) {
      console.warn(`目标时间不在无人机的可用性时间范围内`);
      return false;
    }

    // 设置viewer的时钟时间
    this.viewer.clock.currentTime = targetTime;

    // 验证无人机在目标时间的位置是否存在
    const position = uavItem.uavIcon.position.getValue(targetTime);
    if (!position) {
      console.warn(`无法获取无人机在时间 ${Cesium.JulianDate.toIso8601(targetTime)} 的位置`);
      return false;
    }

    console.log(`成功跳转到无人机 ${snCode} 在时间 ${Cesium.JulianDate.toIso8601(targetTime)} 的位置`);
    return true;
  }

  getHistoryInfo (snCode) {
    return this.historyInfo[snCode] || null;
  }

  /**
   * 开始播放所有无人机轨迹
   * @returns {boolean} 是否开始播放成功
   */
  startPlay () {
    // 获取所有轨迹模式的无人机
    const trackModeUavs = [];
    this.uavLayer.forEach((uavItem, snCode) => {
      if (uavItem.isTrackMode && this.historyInfo[snCode]) {
        trackModeUavs.push({ snCode, uavItem, timeInfo: this.historyInfo[snCode] });
      }
    });

    if (trackModeUavs.length === 0) {
      console.warn('没有轨迹模式的无人机可以播放');
      return false;
    }

    // 找到最早的开始时间和最晚的结束时间
    let globalStartTime = null;
    let globalStopTime = null;
    let playbackSpeed = 1.0;

    trackModeUavs.forEach(({ timeInfo }) => {
      if (!globalStartTime || Cesium.JulianDate.lessThan(timeInfo.startTime, globalStartTime)) {
        globalStartTime = timeInfo.startTime;
      }
      if (!globalStopTime || Cesium.JulianDate.greaterThan(timeInfo.stopTime, globalStopTime)) {
        globalStopTime = timeInfo.stopTime;
      }
      // 使用第一个无人机的播放速度作为全局播放速度
      if (timeInfo.playbackSpeed) {
        playbackSpeed = timeInfo.playbackSpeed;
      }
    });

    // 设置时钟播放速度
    this.viewer.clock.multiplier = playbackSpeed;

    // 确定开始播放的时间点
    // 优先使用已保存的当前时间，如果没有则使用全局开始时间
    let resumeTime = globalStartTime;

    // 查找是否有无人机保存了当前播放时间
    for (const { timeInfo } of trackModeUavs) {
      if (timeInfo.currentTime) {
        resumeTime = timeInfo.currentTime;
        break;
      }
    }

    // 设置时钟时间范围
    this.viewer.clock.startTime = globalStartTime;
    this.viewer.clock.stopTime = globalStopTime;
    this.viewer.clock.currentTime = resumeTime;
    this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;

    // 开始播放
    this.viewer.clock.shouldAnimate = true;

    console.log(`开始播放 ${trackModeUavs.length} 个无人机的轨迹，从时间 ${Cesium.JulianDate.toIso8601(resumeTime)} 开始`);
    return true;
  }

  /**
   * 暂停所有无人机轨迹播放
   * @returns {boolean} 是否暂停成功
   */
  plusEnd () {
    // 获取所有轨迹模式的无人机
    const trackModeUavs = [];
    this.uavLayer.forEach((uavItem, snCode) => {
      if (uavItem.isTrackMode && this.historyInfo[snCode]) {
        trackModeUavs.push({ snCode, uavItem, timeInfo: this.historyInfo[snCode] });
      }
    });

    if (trackModeUavs.length === 0) {
      console.warn('没有轨迹模式的无人机可以暂停');
      return false;
    }

    // 暂停播放
    this.viewer.clock.shouldAnimate = false;

    // 获取当前时钟时间
    const currentTime = this.viewer.clock.currentTime;

    // 为每个轨迹模式的无人机更新historyInfo中的currentTime
    trackModeUavs.forEach(({ snCode, timeInfo }) => {
      this.historyInfo[snCode] = {
        ...timeInfo,
        currentTime: currentTime
      };
    });

    console.log(`暂停 ${trackModeUavs.length} 个无人机的轨迹播放，当前时间：${Cesium.JulianDate.toIso8601(currentTime)}`);
    return true;
  }

}